package com.junchenrobot.mes.handler;

import com.junchenrobot.mes.config.PlcProperties;
import com.junchenrobot.mes.core.DBReadAndWrite;
import com.junchenrobot.mes.exceptions.PLCException;
import com.sourceforge.snap7.moka7.S7Client;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * 卷绕机plc客户端
 *
 * @author SeaWave
 * @date 2023/01/13
 */
@Slf4j
public class PlcClient {
    
    /**
     * 属性
     */
    private final PlcProperties properties;
    
    /**
     * 属性
     */
    private final DBReadAndWrite readAndWrite;
    
    private final Integer winderReadDB;
    
    private final Integer winderWriteDB;
    
    private final Integer transferReadDB;

    private final Integer transferWriteDB;
    
    private final String host;

    public PlcClient(PlcProperties properties) {
        this.properties = properties;
        readAndWrite = new DBReadAndWrite();
        winderReadDB = properties.getWinderReadDB();
        winderWriteDB = properties.getWinderWriteDB();
        transferReadDB = properties.getTransferReadDB();
        transferWriteDB = properties.getTransferWriteDB();
        host = properties.getHost();

    }
    /**
     *  引入S7plc
     */

    /**
     * 查询卷绕机是否准备好
     *
     * @param offset 偏移量
     */
    public boolean winderReady(int offset)  {
        boolean result = false;
        // 连接PLC客户端
        try{
            //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
            S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
            // 读取数据
            byte[] readData = readAndWrite.readBitData(s7Client, winderReadDB, offset);
            // 判断第二位是否为正确的值
            if (readAndWrite.getBit(readData, 1)) {
                result = true;
            }
            // 断开连接
            readAndWrite.disconnect(s7Client);
            return result;
        }catch (PLCException e){
            return false;
        }

    }
    
    /**
     * 卷绕机开始推
     *
     * @param offset 偏移量
     * @return
     * @throws PLCException PLC异常
     */
    public boolean winderStartPush(int offset)  {

        try{
            boolean result = false;
            // 连接PLC客户端
            S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
            //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
            // 读取 写DB 块数据 作为原始值
            byte[] readData = readAndWrite.readBitData(s7Client, winderWriteDB, offset);
            if (readAndWrite.getBit(readData, 1)) {
                result = true;
            } else {
                // 更新值
                byte[] write = readAndWrite.setBit(readData, 1, true);
                // 写入数据
                readAndWrite.winderBitDB(s7Client, winderWriteDB, offset, write);
            }
            // 断开连接
            readAndWrite.disconnect(s7Client);
            return result;

    }catch (PLCException e){
        return false;
    }

    }
    
    /**
     * 卷绕机推完成了
     *
     * @param offset 偏移量
     * @throws PLCException PLC异常
     */
    public boolean winderPushFinished(int offset) {
        try{
            boolean result = false;
            // 连接PLC客户端
            S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
            //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
            // 读取 读DB 块数据
            byte[] readData = readAndWrite.readBitData(s7Client, winderReadDB, offset);
            // 断开连接
            readAndWrite.disconnect(s7Client);
            return readAndWrite.getBit(readData, 4);
        }catch (PLCException e){
            return false;
        }
    }
    
    /**
     * 卷绕机清除推信号
     *
     * @param offset 偏移量
     * @return boolean
     * @throws PLCException PLC异常
     */
    public boolean winderCleanPush(int offset)  {
        boolean result = false;
try{
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    // 读取 写DB 块数据 作为原始值
    byte[] readData = readAndWrite.readBitData(s7Client, winderWriteDB, offset);
    if (!readAndWrite.getBit(readData, 1)) {
        result = true;
    } else {
        // 更新值
        byte[] write = readAndWrite.setBit(readData, 1, false);
        // 写入数据
        readAndWrite.winderBitDB(s7Client, winderWriteDB, offset, write);
    }
    // 断开连接
    readAndWrite.disconnect(s7Client);
    return result;

    }catch (PLCException e){
        return false;
    }
    }
    
    
    /**
     * 中转站取货请求置1
     */
    public boolean transferRequest(int offset,int offset2)  {
        boolean result = false;

try{
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    // 读取 写DB作为初始值
    if (offset2!=0){
        byte[] readData = readAndWrite.readBitData(s7Client, transferWriteDB, offset);
        byte[] readData2 = readAndWrite.readBitData(s7Client, transferWriteDB, offset2);
        if (readAndWrite.getBit(readData, 0) && readAndWrite.getBit(readData2, 0)) {
            result = true;
        } else {
            readAndWrite.setBit(readData, 0, true);
            readAndWrite.setBit(readData2, 0, true);
            // 写入数据
            readAndWrite.winderBitDB(s7Client, transferWriteDB, offset, readData);
            readAndWrite.winderBitDB(s7Client, transferWriteDB, offset2, readData2);
        }
    }else {
        byte[] readData = readAndWrite.readBitData(s7Client, transferWriteDB, offset);
        // 取货请求置为1
        if (readAndWrite.getBit(readData, 0)) {
            result = true;
        } else {
            readAndWrite.setBit(readData, 0, true);
            // 写入数据
            readAndWrite.winderBitDB(s7Client, transferWriteDB, offset, readData);
        }
    }
    readAndWrite.disconnect(s7Client);
    return result;
    }catch (PLCException e){
        return false;
    }
    }
    
    
    /**
     * 读中转站到位信号
     */
    public boolean transferInplace(int offset,int offset2)  {
        boolean result = false;

try{
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    // 读取 写DB作为初始值
    if (offset2!=0){
        byte[] readData = readAndWrite.readBitData(s7Client, transferReadDB, offset);
        byte[] readData2 = readAndWrite.readBitData(s7Client, transferReadDB, offset2);
        if (readAndWrite.getBit(readData, 0)&&readAndWrite.getBit(readData2, 0)) {
            result = true;
        }
        return result;
    }
    byte[] readData = readAndWrite.readBitData(s7Client, transferReadDB, offset);
    if (readAndWrite.getBit(readData, 0)) {
        result = true;
    }
    //断开连接
    readAndWrite.disconnect(s7Client);
    return result;

    }catch (PLCException e){
        return false;
    }
    }


    
    /**
     * 中转站正在取货
     *
     * @return
     */
    public boolean transferRunning(int offset,int offset2)  {
        boolean result = false;


try{
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    if (offset2!=0){
        byte[] readData = readAndWrite.readBitData(s7Client, transferWriteDB, offset);
        byte[] readData2 = readAndWrite.readBitData(s7Client, transferWriteDB, offset2);
        // 正在取货置为1
        if (readAndWrite.getBit(readData, 2)&&readAndWrite.getBit(readData2, 2)) {
            result = true;
        } else {
            readAndWrite.setBit(readData, 2, true);
            readAndWrite.setBit(readData2, 2, true);
            // 写入数据
            readAndWrite.winderBitDB(s7Client, transferWriteDB, offset, readData);
            readAndWrite.winderBitDB(s7Client, transferWriteDB, offset2, readData2);
        }
    }else{
        // 读取 写DB作为初始值
        byte[] readData = readAndWrite.readBitData(s7Client, transferWriteDB, offset);

        // 正在取货置为1
        if (readAndWrite.getBit(readData, 2)) {
            result = true;
        } else {
            readAndWrite.setBit(readData, 2, true);
            // 写入数据
            readAndWrite.winderBitDB(s7Client, transferWriteDB, offset, readData);
        }
    }
    readAndWrite.disconnect(s7Client);
    return result;


    }catch (PLCException e){
        return false;
    }
    }
    
    
    /**
     * 中转站取货完成
     *
     * @return
     */
    public boolean transferFinished(int offset)  {
        boolean result = false;

try{


    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    // 读取 写DB作为初始值
    byte[] readData = readAndWrite.readBitData(s7Client, transferWriteDB, offset);
    // 正在取货置为1
    if (readAndWrite.getBit(readData, 1)) {
        result = true;
    } else {
        readAndWrite.setBit(readData, 1, true);
        // 写入数据
        readAndWrite.winderBitDB(s7Client, transferWriteDB, offset, readData);
    }
    readAndWrite.disconnect(s7Client);
    return result;
    }catch (PLCException e){
        return false;
    }
    }

    /**
     * 写入产线机号,流水号
     * @param offset
     * @param line
     * @param spinning
     * @param type
     * @return
     * @throws PLCException
     */
    public boolean transferInfo(int offset, int line, int spinning, int type) {
        //boolean result = false;

try{
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    // 读取 写DB作为初始值
    log.info("写入Line");
    byte[] readDataLine = readAndWrite.readIntData(s7Client, transferWriteDB, offset + 4);
    readAndWrite.setInt(readDataLine, 0, line);
    readAndWrite.writeIntData(s7Client, transferWriteDB, offset + 4, readDataLine);

    log.info("写入Spinning");
    byte[] readDataSpinning = readAndWrite.readIntData(s7Client, transferWriteDB, offset + 2);
    readAndWrite.setInt(readDataSpinning, 0, spinning);
    readAndWrite.writeIntData(s7Client, transferWriteDB, offset + 2, readDataSpinning);

    log.info("写入Lsh");
    // 读取 写DB作为初始值
    byte[] readDInt = readAndWrite.readDIntData(s7Client, transferWriteDB, offset + 6);
    readAndWrite.setDInt(readDInt, 0, type);
    readAndWrite.writeDIntData(s7Client, transferWriteDB, offset + 6, readDInt);
    readAndWrite.disconnect(s7Client);
    return true;

    }catch (PLCException e){
        return false;
    }
    }
    
    
    /**
     * 中转站清除取货请求
     *
     * @return
     */
    public boolean tranferClearRequest(int offset)    {

try{
    TimeUnit.SECONDS.sleep(5);
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(host, 102);
    //S7Client s7Client = S7ClientEnm.getInstance(host);
    // 读取 写DB作为初始值
    byte[] readData = readAndWrite.readBitData(s7Client, transferWriteDB, offset);
    readAndWrite.setBit(readData, 0, false);
    readAndWrite.setBit(readData, 1, false);
    readAndWrite.setBit(readData, 2, false);
    // 写入数据
    readAndWrite.winderBitDB(s7Client, transferWriteDB, offset, readData);
    transferInfo(offset, 0, 0, 0);
    readAndWrite.disconnect(s7Client);
    return true;
    }catch (PLCException | InterruptedException e){
        return false;
    }
    }

    /**
     * 门开到位
     */
    public boolean doorInplace(int offset)  {
        boolean result = false;

try{
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    // 读取 写DB作为初始值 1门 offset=22  2门 offset=32
    byte[] readData = readAndWrite.readIntData(s7Client, transferReadDB, offset);
    log.info("读开门");
    for (byte b:  readData){
        log.info("{}",b);
    }

    // log.info("getInt{}",readAndWrite.getInt(readData, 0));
    if (readData[1] == 1) {
        log.info("读到开门保持!");
        result = true;
    }
    readAndWrite.disconnect(s7Client);
    return result;
    }catch (PLCException e){
        return false;
    }
    }

    /**
     * 写入关门
     *
     * @return
     */
    public boolean closeTheDoor(int offset,int door)  {

try{
    //boolean result = false;
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    // 读取 写DB作为初始值
    log.info("写入关门");
    byte[] readCloseTheDoor = readAndWrite.readIntData(s7Client, transferWriteDB, offset);
    readAndWrite.setInt(readCloseTheDoor, 0, door);

    readAndWrite.writeIntData(s7Client, transferWriteDB, offset, readCloseTheDoor);
    // 断开连接
    readAndWrite.disconnect(s7Client);
    return true;

    }catch (PLCException e){
        return false;
    }
    }
    /**
     * 写入开门保持
     *
     * @return
     */
    public boolean doorHolding(int offset,int door)  {

try{
    //boolean result = false;
    // 连接PLC客户端
    S7Client s7Client = readAndWrite.connectPLC(properties.getHost(), 102);
    //S7Client s7Client = S7ClientEnm.getInstance(properties.getHost());
    // 读取 写DB作为初始值
    log.info("写入开门保持");
    byte[] readDoorHolding = readAndWrite.readIntData(s7Client, transferWriteDB, offset+2);
    readAndWrite.setInt(readDoorHolding, 0, door);
    readAndWrite.writeIntData(s7Client, transferWriteDB, offset+2, readDoorHolding);
    readAndWrite.disconnect(s7Client);
    return true;

    }catch (PLCException e){
        return false;
    }
    }
}
